package uk.ac.glasgow.oose2.gcf.model.tests;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import uk.ac.glasgow.oose2.gcf.model.CalculatorException;
import uk.ac.glasgow.oose2.gcf.model.ScientificCalculator;

public class ScientificCalculatorTest extends BasicCalculatorTest {

	/** Provides an interface to the extended features of the calculator under test */
	private ScientificCalculator sciCalc;

	@Before
	@Override
	public void setUp() throws Exception {
		sciCalc = new ScientificCalculator();
		//Make sure that the basic functionality of the scientific calculator
		//hasn't been broken.
		theCalc = sciCalc;
	}

	@After
	public void tearDown() throws Exception {
		theCalc.clear();
	}

	/**
	 * Tests ScientificCalculator.e()
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testE() throws CalculatorException{
		sciCalc.e();
		Double result = sciCalc.result();
		assertEquals(Math.E,result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.ln() for argument 10.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testLn()  throws CalculatorException{
		sciCalc.enter(10.0);
		sciCalc.ln();
		Double result = sciCalc.result();
		assertEquals(Math.log(10),result,epsilon);
	}
	
	/**
	 * Tests ScientificCalculator.ln() for argument 0.0
	 * Fails if an exception is not thrown
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testLn0()  {
		try
		{
			sciCalc.enter(0.0);
			sciCalc.ln();
			sciCalc.result();
			fail("Invalid domain value");
		}
		catch(CalculatorException c)
		{}
	}

	/**
	 * Tests ScientificCalculator.ln() for argument -10.0
	 * Fails if an exception is not thrown
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testLn1()  {
		try
		{
			sciCalc.enter(-10.0);
			sciCalc.ln();
			sciCalc.result();
			fail("Invalid domain value");
		}
		catch(CalculatorException c)
		{}
	}

	/**
	 * Tests ScientificCalculator.exp() for argument 10.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testExp()  throws CalculatorException{
		sciCalc.enter(10.0);
		sciCalc.exp();
		Double result = sciCalc.result();
		assertEquals(Math.exp(10),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.exp() for argument -10.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testExp1()  throws CalculatorException{
		sciCalc.enter(-10.0);
		sciCalc.exp();
		Double result = sciCalc.result();
		assertEquals(Math.exp(-10),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.pow() for arguments 2.0 and 10.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testPow()  throws CalculatorException{
		sciCalc.enter(2.0);
		sciCalc.enter(10.0);
		sciCalc.pow();
		Double result = sciCalc.result();
		assertEquals(Math.pow(2,10),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.pow() for arguments 0.0 and 10.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testPow0()  throws CalculatorException{
		sciCalc.enter(0.0);
		sciCalc.enter(10.0);
		sciCalc.pow();
		Double result = sciCalc.result();
		assertEquals(Math.pow(0,10),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.pow() for arguments 2.0 and 0.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testPow1()  throws CalculatorException{
		sciCalc.enter(2.0);
		sciCalc.enter(0.0);
		sciCalc.pow();
		Double result = sciCalc.result();
		assertEquals(Math.pow(2,0),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.rad() for argument Pi/2
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testRad()  throws CalculatorException{
		sciCalc.enter(90.0);
		sciCalc.rad();
		Double result = sciCalc.result();
		assertEquals(Math.PI/2.0,result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.rad() for argument 0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testRad0()  throws CalculatorException{
		sciCalc.enter(0.0);
		sciCalc.rad();
		Double result = sciCalc.result();
		assertEquals(0,result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.rad() for argument -Pi
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testRad1()  throws CalculatorException{
		sciCalc.enter(-180.0);
		sciCalc.rad();
		Double result = sciCalc.result();
		assertEquals(-Math.PI,result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.sin() for argument Pi/2
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testSin()  throws CalculatorException{
		sciCalc.enter(Math.PI/2);
		sciCalc.sin();
		Double result = sciCalc.result();
		assertEquals(Math.sin(Math.PI/2),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.sin() for argument 0.0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testSin0()  throws CalculatorException{
		sciCalc.enter(0.0);
		sciCalc.sin();
		Double result = sciCalc.result();
		assertEquals(Math.sin(0),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.sin() for argument -Pi
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testSin1()  throws CalculatorException{
		sciCalc.enter(-Math.PI);
		sciCalc.sin();
		Double result = sciCalc.result();
		assertEquals(Math.sin(-Math.PI),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.cos() for argument Pi
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testCos()  throws CalculatorException{
		sciCalc.enter(Math.PI);
		sciCalc.cos();
		Double result = sciCalc.result();
		assertEquals(Math.cos(Math.PI),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.cos() for argument 0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testCos0()  throws CalculatorException{
		sciCalc.enter(0.0);
		sciCalc.cos();
		Double result = sciCalc.result();
		assertEquals(Math.cos(0),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.cos() for argument -Pi/2
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testCos1()  throws CalculatorException{
		sciCalc.enter(-Math.PI/2);
		sciCalc.cos();
		Double result = sciCalc.result();
		assertEquals(Math.cos(-Math.PI/2),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.tan() for argument Pi/4
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testTan()  throws CalculatorException{
		sciCalc.enter(Math.PI/4);
		sciCalc.tan();
		Double result = sciCalc.result();
		assertEquals(Math.tan(Math.PI/4),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.tan() for argument 0
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testTan0()  throws CalculatorException{
		sciCalc.enter(0.0);
		sciCalc.tan();
		Double result = sciCalc.result();
		assertEquals(Math.tan(0),result,epsilon);
	}

	/**
	 * Tests ScientificCalculator.tan() for argument -Pi/2
	 * 
	 * @throws CalculatorException
	 */
	@Test
	public void testTan1()  throws CalculatorException{
		sciCalc.enter(-Math.PI/2);
		sciCalc.tan();
		Double result = sciCalc.result();
		assertEquals(Math.tan(-Math.PI/2),result,epsilon);
	}
}
